<?php
/**
 * This file is part of Hyperf Mall.
 *
 * @link     https://gitee.com/scwlkj/hyperf_mall
 * @contact  hyperf_mall@163.com
 */

namespace App\Repository;

use App\Model\CartModel;
use App\Service\Activity\CouponReceiveService;
use App\Service\Config\AreaService;
use App\Service\Goods\GoodsService;
use App\Service\Goods\ProductService;
use App\Service\Member\AddressService;
use Hyperf\Di\Annotation\Inject;

class PreOrderRepository extends BaseRepository
{
    /**
     * @Inject
     * @var CartModel
     */
    protected $model;

    /**
     * @Inject
     * @var CouponReceiveService
     */
    protected CouponReceiveService $couponReceiveService;

    public function initData(array $ids, int $member_id, int $coupon_receive_id = 0 , int $address_id = 0):array
    {
        // 获取地址信息
        $address = $this->address($member_id, $address_id);

        // 获取购物车商品信息
        $carts = $this->cartGoods($ids, $member_id);

        // 计算运费
        $distribution_price = 0;

        // 计算结算金额
        $goods_money = $this->subMoney($carts);

        // 计算优惠券 优惠信息
        $discount_price = 0;
        $coupon = $this->handleCoupon($member_id, $goods_money, $carts, $coupon_receive_id);
        $money = $goods_money;
        if($coupon['discount_price'] > 0){
            $money = bcsub((string)$goods_money, (string)$coupon['discount_price'], 2);
            $discount_price = $coupon['discount_price'];
        }

        // 组装数据
        return [
            'address'=>$address,
            'carts'=>$carts,
            'goods_money'=>$goods_money,
            'discount_price'=>$discount_price,
            'distribution_price'=>$distribution_price,
            'money'=>$money,
            'coupon'=>$coupon['coupon'],
        ];
    }

    /**
     * Notes: 立即下单初始化订单参数
     * Author: Bruce.z
     * DateTime: 2022/7/21 20:46
     * @param array $param
     * @param int $member_id
     * @return array
     */
    public function initBuy(array $param, int $member_id):array
    {
        // 获取地址信息
        $address = $this->address($member_id);

        $goods = GoodsService::getInstance()->getOne(['id'=>$param['goods_id']], ['id','category_id','name','img','retail_price','cost_price']);
        if(isset($param['product_id']) && !empty($param['product_id'])){
            $product = ProductService::getInstance()->getOne(['id'=>$param['product_id']], ['id','name','img','spec_name','retail_price','cost_price']);
            $goods['retail_price'] = $product['retail_price'];
            $goods['cost_price'] = $product['cost_price'];
            $goods['spec_name'] = $product['spec_name'];
        }
        // 计算运费
        $distribution_price = 0;

        // 计算商品金额
        $goods_money = round($param['goods_number']*$goods['retail_price'], 2);

        // 计算优惠券 优惠信息
        $coupon = $this->handleCoupon($member_id, $goods_money, $goods);
        $money = $goods_money;
        if($coupon['discount_price'] > 0){
            $money = bcsub((string)$goods_money, (string)$coupon['discount_price'], 2);
        }

        // 组装数据
        return [
            'address'=>$address,
            'goods'=>$goods,
            'distribution_price'=>$distribution_price,
            'goods_money'=>$goods_money,
            'money'=>$money,
            'discount_price'=>$coupon['discount_price']??0,
            'coupon'=>$coupon['coupon'],
        ];
    }

    /**
     * Notes: 获取会员收货地址
     * Author: Bruce.z
     * DateTime: 2022/7/9 14:47
     * @param int $member_id
     * @param int $address_id
     * @return array
     */
    private function address(int $member_id,int $address_id = 0) :array
    {
        if($address_id > 0){
            $re = AddressService::getInstance()->getOne(['member_id'=>$member_id,'id'=>$address_id],['*']);
        }else{
            $re = AddressService::getInstance()->getOne(['member_id'=>$member_id,'is_default'=>1],['*']);
        }
        return $re;
        //return AddressService::getInstance()->getAddress($member_id);
    }

    /**
     * Notes: 购物车商品列表
     * Author: Bruce.z
     * DateTime: 2022/7/9 14:45
     * @param array $ids
     * @param int $member_id
     * @return array
     */
    public function cartGoods(array $ids, int $member_id = 0):array
    {
        if(empty($ids)){
            $carts = $this->getRows(['is_checked'=>1,'member_id'=>$member_id], ['goods_id','id','product_id','number','member_id']);
        }else{
            $carts = $this->getRows(['id'=>$ids], ['goods_id','id','product_id','number','member_id']);
        }
        $good_ids = $product_ids = [];
        foreach ($carts as $cart){
            if(!empty($cart['product_id'])) $product_ids[] = $cart['product_id'];
            $good_ids[] = $cart['goods_id'];
        }

        $products = [];
        $goods = GoodsService::getInstance()->getRows(['id'=>$good_ids], ['id','name','img','retail_price','cost_price','category_id']);
        $goods = array_column($goods, null, 'id');

        if(count($product_ids)){
            $products = ProductService::getInstance()->getRows(['id'=>$product_ids], ['goods_id','id','name','img','spec_name','retail_price','cost_price']);
            $products = array_column($products, null, 'id');
            foreach ($products as $k=>$val){
                $products[$k]['category_id'] = $goods[$val['goods_id']]['category_id'];
            }
        }

        foreach ($carts as &$cart)
        {
            $cart['goods'] = !empty($cart['product_id']) ? ($products[$cart['product_id']]??[]) : ($goods[$cart['goods_id']]??[]);
            $cart['goods']['img'] = $goods[$cart['goods_id']]['img'];// 覆盖商品图片
            $cart['goods']['name'] = $goods[$cart['goods_id']]['name'];// 覆盖商品名字
            $cart['category_id'] = $goods[$cart['goods_id']]['category_id'];
        }

        return $carts;
    }

    public function getBuyGoods(int $goods_id, int $product_id)
    {
        $goods = GoodsService::getInstance()->getOne(['id'=>$goods_id], ['id','name','img','retail_price','cost_price']);
        if($product_id){
            $product = ProductService::getInstance()->getOne(['id'=>$product_id], ['id','name','img','spec_name','retail_price','cost_price']);

            $goods['retail_price'] = $product['retail_price'];
            $goods['spec_name'] = $product['spec_name'];
            $goods['cost_price'] = $product['cost_price'];
            $goods['product_id'] = $product_id;
        }

        return $goods;
    }

    public function subMoney($carts)
    {
        $money  = 0.00;
        array_map(function ($cart) use (&$money){
            $money += $cart['number'] * $cart['goods']['retail_price'];
        },$carts);

        return round($money, 2);
    }

    /**
     * Notes: 判断可用优惠券，最大优惠金额排序
     * Author: Bruce.z
     * DateTime: 2022/9/14 16:06
     * @param $member_id
     * @param $money
     * @param $product
     * @param int $coupon_receive_id
     * @return array
     */
    private function handleCoupon($member_id,$money, $product, int $coupon_receive_id = 0): array
    {
        $data = ['discount_price'=>0,'coupon'=>[]];

        // 获取可用优惠券
        $coupon_list = $this->couponReceiveService->memberCoupon(['member_id'=>$member_id,'status'=>0],1,100);
        if(!$coupon_list['total']) return $data;

        $coupon_list_data = $coupon_list['data'];
        $discount_price = 0;
        foreach ($coupon_list_data as $k=>$v){
            $sub_money = $money;
            // 判断指定分类券是否可用

            $_money = 0;// 可参与券的商品金额是多少
            if($v['goods_type'] == 3){ //指定分类可用
                $ids = explode(',', $v['goods_category']);
                if(isset($product['id'])){
                    // 单个商品处理
                    if(!in_array($product['category_id'], $ids)){
                        unset($coupon_list_data[$k]);
                        continue;
                    }
                }else{
                    $tag = false;
                    foreach ($product as $p){
                        if(in_array($p['category_id'], $ids)){
                            $_money += $p['retail_price']*$p['number'];
                            $tag = true;
                        }
                    }
                    if(!$tag){
                        unset($coupon_list_data[$k]);
                        continue;
                    }
                    $sub_money = $_money;
                }
            }

            if($v['price'] != 0 && $v['price'] > $sub_money){
                unset($coupon_list_data[$k]);
                continue;
            }

            if($v['free_type'] == 1){
                // 满减
                $coupon_list_data[$k]['money'] = max(bcsub((string)$sub_money, (string)$v['coupon_price'], 2), 0);
                $coupon_list_data[$k]['discount_money'] = min($v['coupon_price'], $sub_money);
            }else{
                // 满折扣
                $discount = bcmul((string)$sub_money, (string)($v['coupon_price']/10), 2);
                $coupon_list_data[$k]['money'] = $discount;
                $coupon_list_data[$k]['discount_money'] = bcsub((string)$sub_money, (string)$discount, 2);
            }

            if($coupon_receive_id > 0 && $coupon_receive_id == $v['id']){
                $discount_price = $coupon_list_data[$k]['discount_money'];
            }
        }
        $coupon_list_data = collect($coupon_list_data)->sortByDesc('discount_money')->all();
        $coupon_list_data = array_values($coupon_list_data);

        $discount_price = $discount_price > 0 ? $discount_price :  ($coupon_list_data[0]['discount_money']??0);
        // 返回数据
        return ['discount_price'=>$discount_price,'coupon'=>$coupon_list_data];
    }
}
